package cn.kgc.config;

import cn.kgc.utils.Constants;
import cn.kgc.utils.EmptyUtils;
import com.alibaba.fastjson.JSONObject;
import cn.kgc.dto.Page;
import org.apache.log4j.Logger;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
import java.net.InetAddress;
import java.net.UnknownHostException;

@Component
public class EsUtils {

    //操作es的客户端
    private static TransportClient client = null;
    Logger logger = Logger.getLogger(EsUtils.class);

    //连接对象
    @Autowired
    private EsConnection esConnection;

    //获取es的服务的连接
    public void getConnection() throws UnknownHostException, UnknownHostException {
        //创建对象
        Settings settings = Settings.builder()
                .put("cluster.name", esConnection.getClusterName())
                .build();

        if (client == null)
            client = new PreBuiltTransportClient(settings)
                    .addTransportAddress(
                            new TransportAddress(
                                    InetAddress.getByName(esConnection.getIp()),
                                    esConnection.getPort()));
    }




    //条件查询es中数据，返回分页数据
    public Page queryPage(AbstractEsQuery itemEsQuery) throws Exception {
        Page page = null;


        if (EmptyUtils.isEmpty(itemEsQuery)) {
            logger.info("================条件未正确设置=================");
            return page;
        }

        getConnection();
        SearchRequestBuilder searchRequestBuilder
                = client.prepareSearch(
                itemEsQuery.getIndexName());


        //SearchRequestBuilder,去哪里查询数据吗，index,type，起始位置，页大小
        searchRequestBuilder.setTypes(itemEsQuery.getTypeName());
        searchRequestBuilder.setSearchType(SearchType.QUERY_THEN_FETCH);
        searchRequestBuilder.setExplain(true);

        if (EmptyUtils.isNotEmpty(itemEsQuery.getAsc())) {
            searchRequestBuilder.addSort(itemEsQuery.getAsc(), SortOrder.ASC);
        }if (EmptyUtils.isNotEmpty(itemEsQuery.getDesc())) {
            searchRequestBuilder.addSort(itemEsQuery.getDesc(), SortOrder.DESC);
        }if (EmptyUtils.isEmpty(itemEsQuery.getPageSize())) {
            itemEsQuery.setPageSize(Constants.DEFAULT_PAGE_SIZE);
        }if (EmptyUtils.isEmpty(itemEsQuery.getPageNo())) {
            itemEsQuery.setPageNo(Constants.DEFAULT_PAGE_NO);
        }
        Integer beginPos = (itemEsQuery.getPageNo() - 1)
                * itemEsQuery.getPageSize();

        searchRequestBuilder.setFrom(beginPos);
        searchRequestBuilder.setSize(itemEsQuery.getPageSize());



        //list，存模糊查询的条件
        List<MatchQueryBuilder> matchQueryBuilders = new ArrayList<>();
        //list，存精确查询的条件
        List<TermQueryBuilder> termQueryBuilders = new ArrayList<>();
        //list 存范围查询的条件
        List<RangeQueryBuilder> rangeQueryBuilders = new ArrayList<>();


        // term
        if (EmptyUtils.isNotEmpty(itemEsQuery.getMatchParams())) {
            for (Map.Entry<String, Object> entry : itemEsQuery.getMatchParams().entrySet()) {
                termQueryBuilders.add(QueryBuilders.termQuery(entry.getKey(), entry.getValue()));
            }
        }
        // match
        if (EmptyUtils.isNotEmpty(itemEsQuery.getLikeMatchParams())) {
            for (Map.Entry<String, Object> entry : itemEsQuery.getLikeMatchParams().entrySet()) {
                matchQueryBuilders.add(QueryBuilders.matchQuery(entry.getKey(), entry.getValue()));
            }
        }
        // range <=
        if (EmptyUtils.isNotEmpty(itemEsQuery.getLteParams())) {
            for (Map.Entry<String, Object> entry : itemEsQuery.getLteParams().entrySet()) {
                rangeQueryBuilders.add(QueryBuilders.rangeQuery(entry.getKey()).lte(entry.getValue()));
            }
        }
        // range >=
        if (EmptyUtils.isNotEmpty(itemEsQuery.getGteParams())) {
            for (Map.Entry<String, Object> entry : itemEsQuery.getGteParams().entrySet()) {
                rangeQueryBuilders.add(QueryBuilders.rangeQuery(entry.getKey()).gte(entry.getValue()));
            }
        }

        // bool must must_not should filter
        BoolQueryBuilder boolQueryBuilder = null;

        // 匹配度查询
        for (MatchQueryBuilder matchQueryBuilder : matchQueryBuilders) {
            if (EmptyUtils.isEmpty(boolQueryBuilder))
                boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.must(matchQueryBuilder);
        }
        // term
        for (TermQueryBuilder termQueryBuilder : termQueryBuilders) {
            if (EmptyUtils.isEmpty(boolQueryBuilder))
                boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.must(termQueryBuilder);
        }
        // range
        for (RangeQueryBuilder rangeQueryBuilder : rangeQueryBuilders) {
            if (EmptyUtils.isEmpty(boolQueryBuilder))
                boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.must(rangeQueryBuilder);
        }

        searchRequestBuilder.setQuery(boolQueryBuilder);
        logger.info("es search: " + searchRequestBuilder);


        //发送http请求请求es数据， 返回response
        //{
        //  "took": 2193,
        //  "timed_out": false,
        //  "_shards": {
        //    "total": 5,
        //    "successful": 5,
        //    "skipped": 0,
        //    "failed": 0
        //  },
        //  "hits": {
        //    "total": 2,
        //    "max_score": 0.2876821,
        //    "hits": [
        //      {
        //        "_index": "sc_10",
        //        "_type": "user",
        //        "_id": "02",
        //        "_score": 0.2876821,
        //        "_source": {
        //          "name": "李商隐",
        //          "sex": 1,
        //          "address": "深圳龙岗区万象汇",
        //          "age": 55
        //        }
        //      },
        //      {
        //        "_index": "sc_10",
        //        "_type": "user",
        //        "_id": "01",
        //        "_score": 0.16853254,
        //        "_source": {
        //          "name": "李白",
        //          "sex": 1,
        //          "address": "深圳南山区Tcl大厦",
        //          "age": 22
        //        }
        //      }
        //    ]
        //  }
        //}
        SearchResponse response = searchRequestBuilder.execute().actionGet();
        SearchHits searchHits = response.getHits();
        logger.info("es search: " + searchHits.getTotalHits());
        page = new Page(itemEsQuery.getPageNo(), itemEsQuery.getPageSize(),
                new Long(searchHits.getTotalHits()).intValue());


        //数据hits
        SearchHit[] hits = searchHits.getHits();
        List result = null;

        if (EmptyUtils.isNotEmpty(hits)) {
            result = new ArrayList();
                for (SearchHit hit : hits) {
                String json = hit.getSourceAsString();
                System.out.println(json);
                ItemSearchVo t = (ItemSearchVo) JSONObject.parseObject(json,
                        itemEsQuery.getModuleClass());
                result.add(t);
            }
            page.setRows(result);
        }
        return page;
    }
//更新es 操作的方法,增量更新


    //ItemSearchVo  ---> es的document
    public boolean addBatchEsModule(List<ItemSearchVo> esModules) throws Exception {
        boolean flag = false;
        //获取es的连接对象
        getConnection();

        BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
            for (ItemSearchVo esModule : esModules) {
                String json = JSONObject.toJSONString(esModule);
            // PUT index/type/id
            // {
            // }
            bulkRequestBuilder.add(
                    client.prepareIndex(esModule.getIndexName(),
                            esModule.getTypeName(), esModule.getEsId())
                            .setSource(json, XContentType.JSON));
        }


        BulkResponse response = bulkRequestBuilder.execute().actionGet();
        if (response.status().getStatus()==200)
            flag = true;

        return flag;
    }




}
